package com.zjl.spring.config;

import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.MybatisXMLLanguageDriver;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.zjl.spring.enums.DeleteEnums;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

/*
 * mybatis基础配置
 *
 * @Author zhuangjl
 * @Date 2021/11/10 19:13
 **/
@Configuration
@MapperScan({"com.zjl.spring.**.mapper*"})
public class MybatisPlusConfig {

    @Bean
    public SqlSessionFactory sqlSessionFactory(
            @Qualifier("customizeDataSource") DataSource dataSource,
            PaginationInterceptor paginationInterceptor,
            MetaObjectHandler metaObjectHandler) throws Exception {

        //创建mybatis工厂bean
        MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        //指定数据源
        sqlSessionFactoryBean.setDataSource(dataSource);
        //持久化实体所在包
        sqlSessionFactoryBean.setTypeAliasesPackage("com.zjl.spring.domain");
        //枚举类型实体所在包
        sqlSessionFactoryBean.setTypeEnumsPackage("com.zjl.spring.enums");

        //MyBatis配置类
        MybatisConfiguration configuration = new MybatisConfiguration();
        //指定一个对XML文件解析的驱动类
        configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
        //对空值指定一个JDBC TYPE
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        //可以java驼峰命名的字段和数据库命名的字段进行适配
        configuration.setMapUnderscoreToCamelCase(true);
        //是否对配置进行缓存
        configuration.setCacheEnabled(false);
        //可以自定义枚举处理类
        //configuration.setDefaultEnumTypeHandler(UniversalEnumHandler.class);

        sqlSessionFactoryBean.setConfiguration(configuration);
        //设置分页插件
        sqlSessionFactoryBean.setPlugins(paginationInterceptor);

        //创建全局配置类
        GlobalConfig globalConfig = new GlobalConfig();
        //自定义填充策略接口实现
        globalConfig.setMetaObjectHandler(metaObjectHandler);
        //开启SQL解析缓存注解生效，开启后多租户 @SqlParser 注解生效
        //globalConfig.setSqlParserCache(true);

        //创建全局配置类
        GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();
        //雪花算法，主键类型：ID_WORKER(com.baomidou.mybatisplus.core.incrementer.SnowflakeIdGenerator)。
        dbConfig.setIdType(IdType.ID_WORKER);
        // 字段策略
        dbConfig.setUpdateStrategy(FieldStrategy.NOT_EMPTY);
        dbConfig.setInsertStrategy(FieldStrategy.NOT_EMPTY);
        // 驼峰下划线转换
        dbConfig.setTableUnderline(true);
        // 数据库大写下划线转换
        dbConfig.setCapitalMode(true);
        // 序列接口实现类配置
        // globalConfiguration.setKeyGenerator(keyGenerator);

        // 逻辑删除配置
        dbConfig.setLogicDeleteValue(String.valueOf(DeleteEnums.DELETE));
        dbConfig.setLogicNotDeleteValue(String.valueOf(DeleteEnums.NOT_DELETE));

        globalConfig.setDbConfig(dbConfig);
        sqlSessionFactoryBean.setGlobalConfig(globalConfig);

        return sqlSessionFactoryBean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSession(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    /**
     * 分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        // 开启 count 的 join 优化,只针对 left join !!!
        return new PaginationInterceptor().setCountSqlParser(new JsqlParserCountOptimize(true))
                .setLimit(10000L);
    }

    @Bean
    public LogicDeleteInterceptor logicDeleteInterceptor() {
        return new LogicDeleteInterceptor();
    }

    /**
     * 自动填充处理器
     */
    @Bean
    public MetaObjectHandler metaObjectHandler() {
        return new CustomizeMetaObjectHandler();
    }
}
